Managing Errors, Forbidden Access, and Observability in Next.js — Graceful Recovery and Smart Monitoring

nextjs-error-boundary-global-error-forbidden-instrumentation-observability

error.jsforbidden.jsinstrumentation.jsError Boundary

~3 min read • Updated Oct 29, 2025

1. error.js — Handling Runtime Errors


The error.js file acts as a React Error Boundary. When an error occurs in a route segment, it displays a fallback UI.

'use client'

export default function Error({ error, reset }) {
  useEffect(() => {
    console.error(error)
  }, [error])

  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  )
}

Key Features:

  • error.message: Debug message
  • error.digest: Unique hash for server-side logs
  • reset(): Attempts to re-render the segment

2. global-error.tsx — Handling Root-Level Errors


Use global-error.tsx to handle errors in the root layout. This file must include html and body tags.

'use client'

export default function GlobalError({ error, reset }) {
  return (
    <html>
      <body>
        <h2>Something went wrong!</h2>
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  )
}

3. GracefullyDegradingErrorBoundary — Elegant Recovery


This component captures the current HTML before an error and re-renders it without hydration, showing a persistent notification bar.

if (this.state.hasError) {
  return (
    <>
      <div dangerouslySetInnerHTML={{ __html: cachedHTML }} />
      <div className="notification">An error occurred</div>
    </>
  )
}

4. forbidden.js — Displaying a 403 Page


The forbidden.js file renders a custom UI when the forbidden() function is triggered during authentication.

export default function Forbidden() {
  return (
    <div>
      <h2>Forbidden</h2>
      <p>You are not authorized to access this resource.</p>
      <Link href="/">Return Home</Link>
    </div>
  )
}

5. instrumentation.js — Observability and Error Tracking


The instrumentation.ts file lets you track server performance and report errors to external services.

export function register() {
  registerOTel('next-app')
}

export const onRequestError = async (err, request, context) => {
  await fetch('https://.../report-error', {
    method: 'POST',
    body: JSON.stringify({ message: err.message, request, context }),
    headers: { 'Content-Type': 'application/json' },
  })
}

Parameters:

  • error.digest: Unique error ID
  • request: Path, method, headers
  • context: Router type, route type, render source, revalidation reason

6. Targeting Runtime


To run different logic in Node.js or Edge:

if (process.env.NEXT_RUNTIME === 'edge') {
  return require('./register.edge')
} else {
  return require('./register.node')
}

Conclusion


Next.js provides robust tools like error.js, forbidden.js, and instrumentation.js to handle errors, control access, and monitor performance. These features help developers build resilient, secure, and user-friendly applications.


Written & researched by Dr. Shahin Siami